#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/keyboard.h>
#include <linux/ioport.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/timer.h> 
#include <linux/clk.h>

#include <linux/power/scenelock.h> 

#include <mach/sys_config.h>
#include <linux/gpio.h>

#define INPUT_DEV_NAME ("volume-key")

#define KEY_NUM 2
static script_item_u item[KEY_NUM];
script_item_value_type_e type;

int irq_num1,irq_num2;

static int get_gpio(){

		int req_status = 0;
		type = script_get_item("volume_para","down",&item[0]);
		if(SCIRPT_ITEM_VALUE_TYPE_PIO != type) {

				printk(KERN_ERR"script_get_item 0 return type err\n");
		}

		req_status = gpio_request(item[0].gpio.gpio, NULL);
		if(0 != req_status) {

				printk(KERN_ERR"request gpio 0 failed\n");
		}



		type = script_get_item("volume_para","up",&item[1]);
		if(SCIRPT_ITEM_VALUE_TYPE_PIO != type) {

				printk(KERN_ERR"script_get_item 1 return type err\n");
		}

		req_status = gpio_request(item[1].gpio.gpio, NULL);
		if(0 != req_status) {

				printk(KERN_ERR"request gpio 0 failed\n");
		}
		return 0;
}


static struct input_dev *volume_dev;

static irqreturn_t up_handler(int irq, void *args){

		input_report_key(volume_dev, KEY_VOLUMEUP, !gpio_get_value(item[1].gpio.gpio));
		input_sync(volume_dev);
		return IRQ_HANDLED;

}

static irqreturn_t down_handler(int irq, void *args){


		input_report_key(volume_dev, KEY_VOLUMEDOWN, !gpio_get_value(item[0].gpio.gpio));
		input_sync(volume_dev);
		return IRQ_HANDLED;
}

static int __init volume_init(void)
{
		int err = 0;

		get_gpio();
		irq_num1 = gpio_to_irq(item[0].gpio.gpio);
		irq_num2 = gpio_to_irq(item[1].gpio.gpio);

		volume_dev = input_allocate_device();
		if(!volume_dev) {
				printk(KERN_DEBUG "volume: not enough memory for input device\n");
				err = -ENOMEM;
		}

		volume_dev->name = INPUT_DEV_NAME;
		volume_dev->phys = "volume/input0";
		volume_dev->evbit[0] = BIT(EV_KEY);
		set_bit(KEY_VOLUMEUP, volume_dev->keybit);
		set_bit(KEY_VOLUMEDOWN, volume_dev->keybit);

		if(request_irq(irq_num1, down_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "volume_down", NULL)){

						err = -EBUSY;
						printk(KERN_DEBUG "request irq failed\n");
						goto fail2;
						}


	if(request_irq(irq_num2, up_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "volume_up", NULL)){

						err = -EBUSY;
						printk(KERN_DEBUG "request irq failed\n");
						goto fail2;
						}

	   err = input_register_device(volume_dev);
	   if(err)
	   		goto fail3;

fail3:
	input_free_device(volume_dev);
fail2:
	free_irq(irq_num1, NULL);
	free_irq(irq_num2, NULL);
fail1:
	printk(KERN_DEBUG "volume_init fail.\n");

	return err;
}

static void __exit volume_exit(void) {

		free_irq(irq_num1, NULL);
		free_irq(irq_num2, NULL);

		input_unregister_device(volume_dev);
		input_free_device(volume_dev);
}


module_init(volume_init);
module_exit(volume_exit);

MODULE_AUTHOR("hmliang");
MODULE_DESCRIPTION("volume-key driver");
MODULE_LICENSE("GPL");
